home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Exception Library -- General exception handling for ANSI C programs
- **
- ** Copyright (C) 1992 Computational Vision and Active Perception Lab. (CVAP),
- ** Royal Institute of Technology, Stockholm.
- **
- ** This library is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU Library General Public
- ** License as published by the Free Software Foundation; either
- ** version 2 of the License, or (at your option) any later version.
- **
- ** This library is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ** Library General Public License for more details.
- **
- ** You should have received a copy of the GNU Library General Public
- ** License along with this library (see COPYING-LIB); if not, write to
- ** the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- ** USA.
- **
- ** Written by
- **
- ** Harald Winroth, Matti Rendahl
- ** Computational Vision and Active Perception Laboratory
- ** Royal Institute of Technology
- ** S-100 44 Stockholm
- ** Sweden
- **
- ** Report bugs to candela-bug@bion.kth.se, and direct all inquiries to
- ** candela@bion.kth.se.
- **
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/ioctl.h>
-
- #include <exception/exception.h>
- #include <exception/exc-err.h>
-
- /* sprintf buffers */
- #define TEXT_BUF_SIZE (4 * 1024)
- #define TEXT_BUF_CHECK_SUM 0x81828384
- #define EMPTY_TEXT_BUF {"", TEXT_BUF_CHECK_SUM}
- typedef struct
- {
- char str[TEXT_BUF_SIZE];
- unsigned int check_sum;
-
- } textBuf;
-
- /* Private functions */
- static excErrFormat* append_format (excErrBuf *buf, excErrFormatTag tag);
- static void make_buf_space (excErrBuf *buf, unsigned int req_len);
- #ifdef HAVE_TERMCAP
- static void append_str (excErrBuf *buf, const char *s);
- #endif
- static void append_nstr (excErrBuf *buf, const char *s, unsigned int n);
- static void tab_to_cur (excErrBuf *buf);
- static void new_line (excErrBuf *buf);
- static void soft_new_line (excErrBuf *buf);
- static int is_left_delim (excErrBuf *buf, char c);
- static int is_right_delim (excErrBuf *buf, char c);
- static int is_white (excErrBuf *buf, char c);
- static void check_text_buf (textBuf *buf);
-
- /* Place-holder representing the excErr type */
- excErrType exc_err_type;
-
- /*
- * exc_err_progname contains the program name if set, or "anonymous program".
- * It is set if exc_err_progname != exc_err_anonymous_program.
- */
-
- char exc_err_anonymous_program[] = "anonymous-program";
- char *exc_err_progname = exc_err_anonymous_program;
-
- /*
- * Access functions for excErr exception variables
- */
-
- excErr *exc_err_domain (excErr *e)
- {
- return e->in_domain;
- }
-
- char *exc_err_name (excErr *e)
- {
- return e->name;
- }
-
- char *exc_err_str (excErr *e)
- {
- return e->str;
- }
-
- excErr *exc_err_top_domain (excErr *e)
- {
- while (exc_err_domain (e))
- e = exc_err_domain (e);
-
- return e;
- }
-
- char *exc_err_package_name (excErr *e)
- {
- /*
- The package name can be found in the 'str' field of the top-level domain.
- If no package name has been specified, use the top-level domain name.
- */
- char *name = exc_err_str (exc_err_top_domain (e));
-
- if (!name)
- name = exc_err_name (exc_err_top_domain (e));
-
- return name;
- }
-
- static void build_full_name (excErr *e, char *buf, unsigned int *len,
- unsigned int buf_size)
- {
- char *s;
- unsigned int n;
-
- if (!e)
- return;
-
- build_full_name (exc_err_domain (e), buf, len, buf_size);
-
- s = exc_err_name (e) ? exc_err_name (e) : "<noname>";
- n = strlen (s);
-
- if (*len + n + 2 > buf_size)
- exc_fatal ("exc_err_full_name: buffer overflow");
-
- strcpy (buf + *len, s);
- strcpy (buf + *len + n, ".");
- *len += n+1;
- }
-
- char *exc_err_full_name (excErr *e)
- {
- static textBuf text_buf = EMPTY_TEXT_BUF;
- unsigned int len = 0;
-
- build_full_name (e, &text_buf.str[0], &len, TEXT_BUF_SIZE);
-
- text_buf.str[len-1] = '\0'; /* Suppress the last '.' */
- return &text_buf.str[0];
- }
-
- /*
- * Creating, destroying and clearing error message buffers
- */
-
- static void init_buf (excErrBuf *buf, char *left_delim, char *right_delim,
- char *white, char *auto_break_char, unsigned int width,
- unsigned int max_tab)
- {
- if (width < 1)
- width = 1;
-
- if (max_tab > width-1)
- max_tab = width-1;
-
- if (!left_delim)
- left_delim = "";
-
- if (!right_delim)
- right_delim = "";
-
- if (!white)
- white = " \t";
-
- if (!auto_break_char || !*auto_break_char)
- auto_break_char = "\\";
-
- buf->width = width;
- buf->max_tab = max_tab;
- buf->left_delim = strcpy (exc_malloc (strlen (left_delim) + 1),
- left_delim);
- buf->right_delim = strcpy (exc_malloc (strlen (right_delim) + 1),
- right_delim);
- buf->whitespace = strcpy (exc_malloc (strlen (white) + 1), white);
- buf->auto_break_char = strcpy (exc_malloc (strlen (auto_break_char) + 1),
- auto_break_char);
-
- buf->str = NULL;
- buf->str_len = 0;
- buf->str_pos = 0;
-
- buf->cur_tab = 0;
- buf->cur_col = 0;
-
- buf->format = NULL;
- buf->format_len = 0;
- buf->format_pos = 0;
- }
-
- static void destroy_buf (excErrBuf *buf)
- {
- unsigned int i;
-
- exc_free (buf->left_delim);
- exc_free (buf->right_delim);
- exc_free (buf->whitespace);
- exc_free (buf->auto_break_char);
-
- for (i=0; i<buf->format_pos; i++)
- if (buf->format[i].tag == excErrStr)
- exc_free (buf->format[i].arg.str);
-
- exc_free (buf->str);
- exc_free (buf->format);
- }
-
- excErrBuf *exc_err_buf_new (excErrBufArg first, ...)
- {
- excErrBuf *buf = (excErrBuf *) exc_malloc (sizeof (excErrBuf));
- char *left_delim = NULL;
- char *right_delim = NULL;
- char *white = NULL;
- char *auto_break_char = "\\";
- unsigned int width = 80;
- unsigned int max_tab = 60;
- va_list rest;
-
- va_start (rest, first);
- while (first)
- {
- switch (first)
- {
- case excErrBufArgLeftDelimiters:
- left_delim = va_arg (rest, char*);
- break;
-
- case excErrBufArgRightDelimiters:
- right_delim = va_arg (rest, char*);
- break;
-
- case excErrBufArgWhitespace:
- white = va_arg (rest, char*);
- break;
-
- case excErrBufArgWidth:
- width = va_arg (rest, unsigned int);
- break;
-
- case excErrBufArgMaxTab:
- max_tab = va_arg (rest, unsigned int);
- break;
-
- case excErrBufArgAutoBreakChar:
- auto_break_char = va_arg (rest, char*);
- break;
-
- default:
- break; /* skip unrecognized key/value pair */
- }
-
- first = va_arg (rest, excErrBufArg);
- }
-
- init_buf (buf, left_delim, right_delim, white, auto_break_char, width,
- max_tab);
-
- va_end (rest);
- return buf;
- }
-
- void exc_err_buf_delete (excErrBuf *buf)
- {
- destroy_buf (buf);
- exc_free (buf);
- }
-
- void exc_err_buf_clear (excErrBuf *buf)
- {
- unsigned int i;
-
- for (i=0; i<buf->format_pos; i++)
- if (buf->format[i].tag == excErrStr)
- exc_free (buf->format[i].arg.str);
-
- exc_free (buf->str);
- exc_free (buf->format);
-
- buf->str = NULL;
- buf->str_len = 0;
- buf->str_pos = 0;
-
- buf->cur_tab = 0;
- buf->cur_col = 0;
-
- buf->format = NULL;
- buf->format_len = 0;
- buf->format_pos = 0;
- }
-
- /*
- * Video attributes (if termcap is available)
- */
-
- static int format_is_on[excErrNumFormatTags] = {0}; /* boolean */
-
- #ifdef HAVE_TERMCAP
-
- extern int tgetent();
- extern char *tgetstr();
-
- static char *termcap_name[excErrNumFormatTags][2 /* {off, on} */] =
- {
- /* underline */ {"ue", "us"},
- /* inverse */ {"me"/* ?? */, "mr"},
- /* stand out */ {"se", "so"}
- /* all additional (non-termcap) fields are set to NULL */
- };
-
- static int termcap_failed = 0;
-
- static char *termcap_str (excErrBuf *buf, char *cap)
- {
- static char str_buf[1024];
- char *str_buf_ptr = &str_buf[0];
- char *str;
-
- if (termcap_failed)
- return NULL;
-
- str = tgetstr (cap, &str_buf_ptr);
- *str_buf_ptr++ = '\0';
-
- return str; /* might be NULL */
- }
-
- static void clear_all_attr (excErrBuf *buf)
- {
- int i;
-
- for (i=0; i<excErrNumFormatTags; i++)
- if (termcap_name[i][0] != NULL)
- append_str (buf, termcap_str (buf, termcap_name[i][0]));
- }
-
- static void reset_all_attr (excErrBuf *buf)
- {
- int i;
-
- clear_all_attr (buf);
-
- for (i=0; i<excErrNumFormatTags; i++)
- if (format_is_on[i] && termcap_name[i][1] != NULL)
- append_str (buf, termcap_str (buf, termcap_name[i][1]));
- }
-
- static void set_attr (excErrBuf *buf, excErrFormatTag attr, int on)
- {
- format_is_on[attr] = on;
- reset_all_attr (buf);
- }
-
- #else
-
- static void clear_all_attr (excErrBuf *buf)
- {
- ; /* no-op */
- }
-
- static void reset_all_attr (excErrBuf *buf)
- {
- ; /* no-op */
- }
-
- static void set_attr (excErrBuf *buf, excErrFormatTag attr, int on)
- {
- format_is_on[attr] = on;
- }
-
- #endif /* HAVE_TERMCAP */
-
-
- /*
- * Primitive formatting calls for error message buffers
- */
-
- static char *handle_newlines (excErrBuf *buf, char *str)
- {
- if (*str == '\n')
- {
- new_line (buf);
- str++;
- return str;
- }
-
- return NULL;
- }
-
- static char *whole_words_on_current_line (excErrBuf *buf, char *str,
- int indivisible)
- {
- int n = buf->width - buf->cur_col; /* n >= 0 */
- int i;
-
- for (i=0; i<n; i++)
- if ((is_white (buf, str[i]) && !indivisible) ||
- (is_right_delim (buf, str[i]) && !indivisible) ||
- (is_white (buf, str[i+1]) && !indivisible) ||
- (is_left_delim (buf, str[i+1]) && !indivisible) ||
- str[i+1]=='\n' || str[i+1]=='\0')
- {
- append_nstr (buf, str, i+1);
- buf->cur_col += i+1;
- str += i+1;
- return str;
- }
-
- return NULL;
- }
-
- static char *whole_words_on_next_line (excErrBuf *buf, char *str,
- int indivisible)
- {
- int n = buf->width - buf->cur_tab; /* n >= 0 */
- int nwhites, i;
-
- for (nwhites=0; is_white (buf, str[nwhites]); nwhites++);
- if (nwhites > 0) /* supress whitespaces after auto-newline */
- {
- soft_new_line (buf);
- str += nwhites;
- return str;
- }
-
- /* First char in str is not whitespace here */
- for (i=0; i<n; i++)
- if ((is_white (buf, str[i]) && !indivisible) ||
- (is_right_delim (buf, str[i]) && !indivisible) ||
- (is_white (buf, str[i+1]) && !indivisible) ||
- (is_left_delim (buf, str[i+1]) && !indivisible) ||
- str[i+1]=='\n' || str[i+1]=='\0')
- {
- soft_new_line (buf);
- append_nstr (buf, str, i+1);
- buf->cur_col += i+1;
- str += i+1;
- return str;
- }
-
- return NULL;
- }
-
- static char *chars_on_current_line (excErrBuf *buf, char *str)
- {
- int n = buf->width - buf->cur_col; /* n >= 0 */
- int max;
-
- if (n>1)
- {
- max = strlen (str);
- if (n-1 > max)
- n = max+1;
-
- append_nstr (buf, str, n-1);
- append_nstr (buf, buf->auto_break_char, 1);
-
- buf->cur_col += n;
- str += n-1;
- return str;
- }
-
- return NULL;
- }
-
- static char *chars_on_next_line (excErrBuf *buf, char *str)
- {
- int n = buf->width - buf->cur_tab; /* n >= 0 */
- int nwhites, max;
-
- if (n>1)
- {
- soft_new_line (buf);
- for (nwhites=0; is_white (buf, str[nwhites]); nwhites++);
-
- max = strlen (str+nwhites);
- if (n-1 > max)
- n = max+1;
-
- append_nstr (buf, str+nwhites, n-1);
- append_nstr (buf, buf->auto_break_char, 1);
-
- buf->cur_col += n;
- str += nwhites+n-1;
- return str;
- }
-
- return NULL;
- }
-
- static char *force_chars_on_current_line (excErrBuf *buf, char *str)
- {
- if (*str)
- {
- append_nstr (buf, str, 1);
- buf->cur_col += 1;
- str += 1;
- }
-
- return str; /* always != NULL */
- }
-
- static void buf_print (excErrBuf *buf, const char *input_str, int indivisible)
- {
- char *str, *next;
-
- if (!input_str)
- return;
-
- str = strcpy (exc_malloc (strlen (input_str) + 1), input_str);
- append_format (buf, excErrStr)->arg.str = str;
-
- for ( ; *str ; str=next)
- {
- /*
- Handle explicit newlines
- */
- next = handle_newlines (buf, str);
- if (next) continue;
-
- /*
- Try to fit a complete word into the current line
- */
- next = whole_words_on_current_line (buf, str, indivisible);
- if (next) continue;
-
- /*
- Check to see if a complete word can fit into line after an
- automatic line break.
- */
- next = whole_words_on_next_line (buf, str, indivisible);
- if (next) continue;
-
- /*
- There is no space for complete words. Try to squeze in as much as
- possible in the current line (without auto line break).
- */
- next = chars_on_current_line (buf, str);
- if (next) continue;
-
- /*
- Make an automatic linebreak and try to squeze in as much as possible
- on that line (after tabulation).
- */
- next = chars_on_next_line (buf, str);
- if (next) continue;
-
- next = force_chars_on_current_line (buf, str); /* panic */
- }
-
- buf->str[buf->str_pos] = '\0'; /* There is always space enough for this */
- }
-
- void exc_err_buf_print (excErrBuf *buf, const char *input_str)
- {
- buf_print (buf, input_str, /* indivisible */ 0);
- }
-
- void exc_err_buf_print_indivis (excErrBuf *buf, const char *input_str)
- {
- buf_print (buf, input_str, /* indivisible */ 1);
- }
-
- void exc_err_buf_vprintf (excErrBuf *buf, const char *fmt, va_list l)
- {
- static textBuf text_buf = EMPTY_TEXT_BUF;
-
- vsprintf (&text_buf.str[0], fmt, l);
- check_text_buf (&text_buf);
-
- exc_err_buf_print (buf, &text_buf.str[0]);
- }
-
- void exc_err_buf_vprintf_indivis (excErrBuf *buf, const char *fmt, va_list l)
- {
- static textBuf text_buf = EMPTY_TEXT_BUF;
-
- vsprintf (&text_buf.str[0], fmt, l);
- check_text_buf (&text_buf);
-
- exc_err_buf_print_indivis (buf, &text_buf.str[0]);
- }
-
- void exc_err_buf_printf (excErrBuf *buf, const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_err_buf_vprintf (buf, fmt, l);
- va_end (l);
- }
-
- void exc_err_buf_printf_indivis (excErrBuf *buf, const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_err_buf_vprintf_indivis (buf, fmt, l);
- va_end (l);
- }
-
- void exc_err_buf_print_buf (excErrBuf *buf, excErrBuf *src)
- {
- unsigned int i;
-
- for (i=0; i<src->format_pos; i++)
- switch (src->format[i].tag)
- {
- case excErrStr:
- exc_err_buf_print (buf, src->format[i].arg.str);
- break;
-
- case excErrTab:
- exc_err_buf_tab (buf, src->format[i].arg.col);
- break;
-
- case excErrUnderline:
- exc_err_buf_underline (buf, src->format[i].arg.on);
- break;
-
- case excErrInverse:
- exc_err_buf_inverse (buf, src->format[i].arg.on);
- break;
-
- case excErrStandOut:
- exc_err_buf_stand_out (buf, src->format[i].arg.on);
- break;
-
- default:
- exc_fatal ("exc_err_buf_print_buf: unknown format tag");
- }
- }
-
- void exc_err_buf_tab (excErrBuf *buf, unsigned int col)
- {
- append_format (buf, excErrTab)->arg.col = col;
-
- if (col > buf->max_tab)
- {
- buf->cur_tab = buf->max_tab;
- if (buf->cur_tab < buf->cur_col+1)
- soft_new_line (buf);
- }
- else
- buf->cur_tab = col;
-
- if (buf->cur_tab< buf->cur_col)
- soft_new_line (buf); /* will tab to current tab column */
- else
- tab_to_cur (buf);
- }
-
- void exc_err_buf_underline (excErrBuf *buf, int on)
- {
- append_format (buf, excErrUnderline)->arg.on = on;
- set_attr (buf, excErrUnderline, on);
- }
-
- void exc_err_buf_inverse (excErrBuf *buf, int on)
- {
- append_format (buf, excErrInverse)->arg.on = on;
- set_attr (buf, excErrInverse, on);
- }
-
- void exc_err_buf_stand_out (excErrBuf *buf, int on)
- {
- append_format (buf, excErrStandOut)->arg.on= on;
- set_attr (buf, excErrStandOut, on);
- }
-
- /*
- * Access functions for excErrBuf
- */
-
- char *exc_err_buf_str (excErrBuf *buf)
- {
- return buf->str;
- }
-
- /*
- * Global error message buffer
- */
-
- excErrBuf *exc_err_buf;
-
- /*
- * exc_err_buf_*() calls on the global exc_err_buf buffer (syntatic sugar)
- */
-
- void exc_err_print (const char *str)
- {
- exc_err_init ();
- exc_err_buf_print (exc_err_buf, str);
- }
-
- void exc_err_print_indivis (const char *str)
- {
- exc_err_init ();
- exc_err_buf_print_indivis (exc_err_buf, str);
- }
-
- void exc_err_printf (const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_err_init ();
- exc_err_buf_vprintf (exc_err_buf, fmt, l);
- va_end (l);
- }
-
- void exc_err_printf_indivis (const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_err_init ();
- exc_err_buf_vprintf_indivis (exc_err_buf, fmt, l);
- va_end (l);
- }
-
- void exc_err_vprintf (const char *fmt, va_list l)
- {
- exc_err_init ();
- exc_err_buf_vprintf (exc_err_buf, fmt, l);
- }
-
- void exc_err_vprintf_indivis (const char *fmt, va_list l)
- {
- exc_err_init ();
- exc_err_buf_vprintf_indivis (exc_err_buf, fmt, l);
- }
-
- void exc_err_tab (unsigned int col)
- {
- exc_err_init ();
- exc_err_buf_tab (exc_err_buf, col);
- }
-
- void exc_err_underline (int on)
- {
- exc_err_init ();
- exc_err_buf_underline (exc_err_buf, on);
- }
-
- void exc_err_inverse (int on)
- {
- exc_err_init ();
- exc_err_buf_inverse (exc_err_buf, on);
- }
-
- void exc_err_stand_out (int on)
- {
- exc_err_init ();
- exc_err_buf_stand_out (exc_err_buf, on);
- }
-
- void exc_err_clear (void)
- {
- exc_err_init ();
- exc_err_buf_clear (exc_err_buf);
- }
-
- /*
- * Throwing an excErr (adds no text to the error message buffer).
- *
- * When exc_err_throw_fatal is used, handler will exit with status 1.
- * When exc_err_throw_nonfatal is used, handler will exit with status 0.
- */
-
- void exc_err_throw_fatal (excErr e)
- {
- exc_throw_typed (e.self, &exc_err_type.fatal);
- }
-
- void exc_err_throw_nonfatal (excErr e)
- {
- exc_throw_typed (e.self, &exc_err_type.nonfatal);
- }
-
- /*
- * Single line error messages
- */
-
- static void print_error_header (excErr e)
- {
- if (exc_err_progname != exc_err_anonymous_program)
- exc_err_printf ("%s: ", exc_err_progname);
-
- exc_err_printf ("%s\n", exc_err_full_name (e.self));
- }
-
- void exc_error (excErr e, const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_verror (e, fmt, l);
- va_end (l); /* Not reached--exc_verror() throws an exception */
- }
-
- void exc_verror (excErr e, const char *fmt, va_list l)
- {
- exc_err_init ();
- print_error_header (e);
-
- if (fmt)
- exc_err_vprintf (fmt, l);
- else
- exc_err_print ((e.str) ? e.str : "undocumented error");
-
- exc_err_throw_fatal (e);
- }
-
- void exc_perror (excErr e, const char *fmt, ...)
- {
- va_list l;
-
- va_start (l, fmt);
- exc_vperror (e, fmt, l);
- va_end (l); /* Not reached--exc_vperror() throws an exception */
- }
-
- void exc_vperror (excErr e, const char *fmt, va_list l)
- {
- char *str = strerror (errno);
-
- exc_err_init ();
- print_error_header (e);
-
- if (fmt)
- exc_err_vprintf (fmt, l);
-
- if (str)
- exc_err_print (str);
- else
- exc_err_printf ("undocumented system error (%d)", errno);
-
- exc_err_throw_fatal (e);
- }
-
- /*
- * Displaying messages (used by exc_err_handler)
- */
-
- void (*exc_err_print_hook)(const char *str) = exc_err_builtin_print;
-
- void exc_err_builtin_print (const char *str)
- {
- fprintf (stderr, "\n%s\n", str);
- }
-
- /* Callback for clearing message buffer */
-
- static void cb (excCallbackTag tag, void *cb_data, void **try_data)
- {
- if (tag == excRecoverCallback)
- exc_err_clear ();
- }
-
- /* Default exception handler */
-
- int exc_err_handler (void *e, void *e_type, void *h_data)
- {
- excErr *ee;
-
- if (!EXC_IN_DOMAIN (e_type, exc_err_type))
- exc_rethrow ();
-
- ee = (excErr *) e;
-
- if (!exc_err_buf_str (exc_err_buf) || !*exc_err_buf_str (exc_err_buf))
- {
- print_error_header (*ee);
- exc_err_printf ("%s\n", (ee->str) ? ee->str : "undocumented error");
- }
-
- (*exc_err_print_hook) (exc_err_buf_str (exc_err_buf));
-
- return EXC_IN_DOMAIN (e_type, exc_err_type.fatal) ? 1 : 0;
- }
-
- /*
- * Initialization
- */
-
- #define EXC_ERR_DEFAULT_WIDTH 80
-
- static int get_tty_width (void)
- {
- #if defined(SVR4) || defined(SYSV) || defined(_SYSV_)
- return EXC_ERR_DEFAULT_WIDTH;
- #else
- struct winsize w;
-
- if (ioctl (fileno (stderr), TIOCGWINSZ, &w))
- return EXC_ERR_DEFAULT_WIDTH; /* ioctl() failed */
- else if (w.ws_col <= 0)
- return EXC_ERR_DEFAULT_WIDTH;
- else
- return (int) (w.ws_col);
- #endif
- }
-
- void exc_err_init (void)
- {
- #ifdef HAVE_TERMCAP
- static char *str_buf[1024];
- char *term_type;
- #endif /* HAVE_TERMCAP */
-
- static int exc_err_inited = 0;
- unsigned min_chars = 20;
- unsigned int max_tab = 0;
- unsigned int width;
-
- if (exc_err_inited)
- return;
-
- width = get_tty_width ();
-
- /* Make sure that at least 'min_chars' chars can be printed on each line */
- if (min_chars < width)
- max_tab = width-min_chars;
- else
- max_tab = 0;
-
- exc_err_buf = exc_err_buf_new (excErrBufArgWidth, width,
- excErrBufArgMaxTab, max_tab,
- excErrBufArgRightDelimiters, ",:;!?)]}",
- excErrBufArgLeftDelimiters, "([{",
- 0);
-
- #ifdef HAVE_TERMCAP
- term_type = getenv ("TERM");
- if (!term_type || tgetent (&str_buf[0], term_type) < 1)
- termcap_failed = 1;
- #endif /* HAVE_TERMCAP */
-
- EXC_INSTALL_HANDLER (exc_any, exc_err_handler, NULL);
- exc_install_callback (excRecoverCallback, cb, NULL);
-
- exc_err_inited = 1;
- }
-
- /*
- * Private
- */
-
- static excErrFormat* append_format (excErrBuf *buf, excErrFormatTag tag)
- {
- /* Note: The return value is valid only until the next call */
-
- excErrFormat *fmt;
-
- if (buf->format_pos == buf->format_len)
- {
- buf->format_len *= 2;
- if (buf->format_len == 0)
- buf->format_len = 32;
-
- buf->format = (excErrFormat *)
- exc_realloc (buf->format, buf->format_len * sizeof (excErrBuf));
- }
-
- fmt = &buf->format[buf->format_pos++];
- fmt->tag = tag;
- return fmt;
- }
-
- static void make_buf_space (excErrBuf *buf, unsigned int req_len)
- {
- /* Always make room for an trailing '\0' */
-
- if (buf->str_pos+req_len+1 > buf->str_len)
- {
- unsigned int inc = buf->str_pos+req_len+1-buf->str_len;
-
- if (buf->str_pos > inc)
- inc = buf->str_pos;
-
- buf->str_len += inc;
- buf->str = (char *) exc_realloc (buf->str, buf->str_len);
- }
- }
-
- static void append_nstr (excErrBuf *buf, const char *s, unsigned int n)
- {
- if (n > 0)
- {
- make_buf_space (buf, n);
- strncpy (&buf->str[buf->str_pos], s, n);
- buf->str_pos += n;
- }
- }
-
- #ifdef HAVE_TERMCAP
- static void append_str (excErrBuf *buf, const char *s)
- {
- append_nstr (buf, s, s ? strlen (s) : 0);
- }
- #endif
-
- static void tab_to_cur (excErrBuf *buf)
- {
- unsigned int delta;
-
- if (buf->cur_col >= buf->cur_tab)
- return;
-
- delta = buf->cur_tab - buf->cur_col;
-
- if (delta > 0)
- {
- clear_all_attr (buf);
- make_buf_space (buf, delta);
- memset (&buf->str[buf->str_pos], ' ', delta);
- buf->str_pos += delta;
- buf->cur_col = buf->cur_tab;
- reset_all_attr (buf);
- }
- }
-
- static void new_line (excErrBuf *buf)
- {
- make_buf_space (buf, 1);
- buf->str[buf->str_pos++] = '\n';
- buf->cur_col = 0;
- buf->cur_tab = 0;
- }
-
- static void soft_new_line (excErrBuf *buf)
- {
- make_buf_space (buf, 1);
- buf->str[buf->str_pos++] = '\n';
- buf->cur_col = 0;
- tab_to_cur (buf);
- }
-
- static int is_left_delim (excErrBuf *buf, char c)
- {
- return (c != '\0' && strchr (buf->left_delim, c) != NULL);
- }
-
- static int is_right_delim (excErrBuf *buf, char c)
- {
- return (c != '\0' && strchr (buf->right_delim, c) != NULL);
- }
-
- static int is_white (excErrBuf *buf, char c)
- {
- return (c != '\0' && strchr (buf->whitespace, c) != NULL);
- }
-
- /*
- * sprintf buffers
- */
-
- static void check_text_buf (textBuf *buf)
- {
- if (buf->check_sum != TEXT_BUF_CHECK_SUM)
- {
- fprintf (stderr,
- "\nexc-err: detected corrupt memory in text buffer.\n");
- fprintf (stderr,
- "exc-err: possible text buffer overflow (text > %d bytes).\n",
- TEXT_BUF_SIZE);
-
- exc_panic();
- }
- }
-